import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import PropTypes from 'prop-types';
import { View } from '@tarojs/components';
import classNames from 'classnames';
import FormContext from './context';
import { checkValue } from './util';
import './index.scss';
/**
 * @name 表单组件
 * @description 用于表单value和校验信息的收集
 * @param {*} props
 */

function Form(props) {
  const requireArr = useRef([]); // 保存 必填校验字段名称   【{name:'price',label: '单价'}】
  const [values, setValues] = useState({}); // 保存 数据
  // const [ requireArr, setRequireArr] = useState([]);// 保存 必填校验字段名称   【‘key1’，'key2'】
  const { initValues } = props;

  // 初始化设置value
  useEffect(() => {
    setValues(initValues);
  }, [initValues]);

  // 设置 value
  const setValue = useCallback(
    (key, value) => {
      setValues((valuesCom)=>{
        return {
          ...valuesCom,
          [key]: value,
        }
      });
    },
    []
  );

  // 保存必填项
  const pushRequireArr = useCallback(key => {
    if (!requireArr.current.length) {
      requireArr.current = [];
    }
    requireArr.current.push(key);
  }, []);

  // 获取 校验后的
  const getFieldsValue = useCallback(() => {
    return values;
  }, [values]);

  // 设置表单的值
  // todo    设置的值有可能会不生效，  子节点也有存  values，一块更新的时候，可能会被覆盖    因为子节点也可可能在操作这个值 哎
  // 在change的时候 和这个在一块使用的时候，要注意一定要 同步操作，不然顺序很难保证   详见  regionSelectItem.js 里面的change
  //
  const setFieldsValue = useCallback((obj) => {
    setValues((valuesCom)=>{
      return{...valuesCom,...obj}
    });
  }, []);

  // 表单校验
  const validateFields = useCallback(
    fun => {
      // 对数据进行校验
      let success = checkValue(requireArr.current,values);
      return fun(values, success);
    },
    [values, requireArr]
  );

  // 放开对外控制
  useEffect(() => {
    const action = {
      getFieldsValue,
      validateFields,
      setFieldsValue,
    };
    const { formRef } = props;
    if (formRef && typeof formRef !== 'function') {
      formRef.current = action;
    }
  }, [getFieldsValue, getFieldsValue, setFieldsValue]);

  const storeValue = useMemo(()=>{
    return { setValue, values, pushRequireArr };
  },[setValue, values, pushRequireArr]);

  const rootClass = classNames(
    'form-wap',
    props.className
  )
  return (
    <FormContext.Provider value={storeValue}>
      <View className={rootClass} style={props.style}>{props.children}</View>
    </FormContext.Provider>
  );
}

Form.defaultProps = {
  initValues:{},
  style:{},
  // onFinish:()=>{},
}
Form.propTypes = {
  /**
   * @初始值
   * */
  initValues:PropTypes.object,
  /**
   * @class
   * */
  className:PropTypes.string,
  /**
   * @style
   * */
  style:PropTypes.object,
  // 提交表单且数据验证成功后回调事件
  // onFinish:PropTypes.any,
}
export default Form;
